﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing;

namespace ImageRecognition2.CustomControls
{
    /// <summary>
    /// 
    /// </summary>
    public class CustomControlListBox : ListBox
    {
        protected bool m_bAutoSizeControls = false;
        /// <summary>
        /// Initializes a new instance of the <see cref="CustomControlListBox"/> class.
        /// </summary>
        public CustomControlListBox()
            : base()
        {
            DrawMode = DrawMode.OwnerDrawVariable;
            this.BackColor = SystemColors.Control;
            this.DoubleBuffered = true;
        }

        /// <summary>
        /// Gets or sets a value indicating whether [auto size controls].
        /// </summary>
        /// <value><c>true</c> if [auto size controls]; otherwise, <c>false</c>.</value>
        public bool AutoSizeControls
        {
            get { return m_bAutoSizeControls; }
            set { m_bAutoSizeControls = value; }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ListBox.MeasureItem"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.MeasureItemEventArgs"/> that contains the event data.</param>
        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            if (this.Items.Count == 0) return;
            if (e.Index == -1) return;
            IEnumerable<Control> aControl = GetControlItems(e.Index);

            if (m_bAutoSizeControls)
            {
                int nCount = 0;
                int nCompleteWidth = 0;

                int nMaxControlHeight = -1;

                ListBoxControlItem item = null;
                foreach (Control control in aControl)
                {
                    nCompleteWidth += control.Width;
                    nCount++;
                    if (control.Height > nMaxControlHeight) nMaxControlHeight = control.Height;
                    item = this.Items[e.Index] as ListBoxControlItem;
                    item.CompleteControlWidth = nCompleteWidth;
                    control.Parent = this;
                }
                item.Count = nCount;
                //int nWidthOfSingleControl = 0;
                e.ItemHeight = nMaxControlHeight;
                e.ItemWidth = nCompleteWidth;
            }
            else
            {
                foreach (Control control in aControl)
                {
                    control.Parent = this;
                    e.ItemHeight = control.Height;
                    e.ItemWidth = control.Width;
                }
            }
            base.OnMeasureItem(e);
        }

        public void AddItem(ListBoxControlItem item)
        {
            //item.Control.MouseLeave += new EventHandler(this.Control_MouseLeave);
            foreach (Control control in item.Controls)
            {
                if (control is Button)
                {
                    control.MouseClick += new MouseEventHandler(this.CloseForm);
                }
                else if (control is ComboBox)
                {
                    ComboBox cob = (ComboBox)control;
                    cob.SelectedIndexChanged += new EventHandler(this.CloseForm);
                }
                else if (control is TextBox)
                {
                    TextBox tb = (TextBox)control;
                    tb.KeyDown += new KeyEventHandler(tb_KeyDown);
                }
                else if (control is ListBox || control is ListView)
                {
                    ListBox lb = (ListBox)control;
                    lb.MouseDoubleClick += new MouseEventHandler(this.CloseForm);
                }
            }
            this.Items.Add(item);
        }

        /// <summary>
        /// Handles the KeyDown event of the tb control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
        void tb_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter)
            {
                this.CloseForm(sender, e);
            }
        }

        /// <summary>
        /// Handles the MouseLeave event of the Control control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void Control_MouseLeave(object sender, EventArgs e)
        {
            Form form = (Form)this.Parent;
            if (form != null)
            {
                form.Close();
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ListBox.DrawItem"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.DrawItemEventArgs"/> that contains the event data.</param>
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (this.Items.Count == 0) return;
            if (e.Index == -1) return;
            Graphics g = e.Graphics;
            g.DrawRectangle(new Pen(Brushes.White), e.Bounds);

            IEnumerable<Control> aControl = GetControlItems(e.Index);

            int nCount = (this.Items[e.Index] as ListBoxControlItem).Count;
            if (m_bAutoSizeControls)
            {
                DrawAutoSizedControls(e, aControl, nCount);
            }
            if (!m_bAutoSizeControls || nCount == 1)
            {
                foreach (Control control in aControl)
                {
                    control.Location = e.Bounds.Location;
                    control.Size = e.Bounds.Size;
                }
            }
            e.DrawFocusRectangle();
            base.OnDrawItem(e);
        }

        /// <summary>
        /// Draws the auto sized controls.
        /// </summary>
        /// <param name="e">The <see cref="System.Windows.Forms.DrawItemEventArgs"/> instance containing the event data.</param>
        /// <param name="aControl">A control.</param>
        /// <param name="nCount">The n count.</param>
        private void DrawAutoSizedControls(DrawItemEventArgs e, IEnumerable<Control> aControl, int nCount)
        {
            int nCompleteWidth = 0;
            int nWidthOfSingleControl = this.Bounds.Size.Width / nCount;
            if (nCount > 1)
            {
                int nOffset = e.Bounds.Location.X;
                foreach (Control control in aControl)
                {
                    control.Location = new Point(nOffset, e.Bounds.Location.Y);
                    control.Size = new Size(nWidthOfSingleControl - this.Margin.Right, e.Bounds.Height);
                    nOffset += nWidthOfSingleControl;
                }
            }
        }

        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        /// <param name="pevent">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains information about the control to paint.</param>
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            pevent.Graphics.FillRectangle(new SolidBrush(SystemColors.Control), pevent.ClipRectangle);
            base.OnPaintBackground(pevent);
        }

        /// <summary>
        /// Gets the control items.
        /// </summary>
        /// <param name="nIndex">Index of the n.</param>
        /// <returns></returns>
        private IEnumerable<Control> GetControlItems(int nIndex)
        {
            if (nIndex == -1) return null;
            ListBoxControlItem item = (ListBoxControlItem)this.Items[nIndex];
            return item.Controls;
        }

        /// <summary>
        /// Closes the form.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void CloseForm(object sender, EventArgs e)
        {
            ((Form)this.Parent).Hide();
        }
    }
}
